package com.atguigu.tingshu.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.account.client.UserAccountFeignClient;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.model.user.VipServiceConfig;
import com.atguigu.tingshu.order.helper.SignHelper;
import com.atguigu.tingshu.order.mapper.OrderDerateMapper;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderDetailService;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.user.client.VipServiceConfigFeignClient;
import com.atguigu.tingshu.vo.account.AccountLockResultVo;
import com.atguigu.tingshu.vo.account.AccountLockVo;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.order.TradeVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private VipServiceConfigFeignClient vipServiceConfigFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private UserAccountFeignClient userAccountFeignClient;

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private OrderDerateMapper orderDerateMapper;

    /**
     * 返回orderNo 跟支付对象
     * @param userId
     * @param orderInfoVo
     * @return
     */
    @Override
    public String submitOrder(Long userId, OrderInfoVo orderInfoVo) {
        //  校验签名：
        String strJson = JSON.toJSONString(orderInfoVo);
        //  将strJson 转换为map 集合
        Map map = JSON.parseObject(strJson, Map.class);
        //  设置支付方式
        map.put("payWay", "");
        //  校验的时候，1. 注意付款方式. 2. 注意所有涉及到的金额初始化值 0.00;
        SignHelper.checkSign(map);
        //  防止重复下单：
        //  先获取到页面传递的流水号
        String tradeNo = orderInfoVo.getTradeNo();
        //  定义缓存的key
        String tradeNoKey = "user:trade:" + userId;
        //  存储到缓存一份,防止重复提交使用！
        //  使用lua 脚本删除. 传入的口令串与键值匹配的时候，就删除锁.
        String scriptText = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        //  创建对象
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(scriptText);
        redisScript.setResultType(Long.class);
        //  调用删除方法.
        Long flag = (Long) this.redisTemplate.execute(redisScript, Arrays.asList(tradeNoKey), tradeNo);
        if (flag == 0) {
            //  throw new GuiguException(ResultCodeEnum.DATA_ERROR);
            throw new GuiguException(ResultCodeEnum.ORDER_SUBMIT_REPEAT);
        }
        //  自定义一个orderNo
        String orderNo = UUID.randomUUID().toString().replaceAll("-","");
        //  判断支付类型： 1101
        if (orderInfoVo.getPayWay().equals(SystemConstant.ORDER_PAY_WAY_WEIXIN)) {
            //  只保存交易记录，对象支付时，才能做支付扣减.
            this.saveOrder(orderInfoVo,userId,orderNo);

        } else {
            try {
                //  余额支付：1103
                //  检查与锁定当前账户可用余额；
                AccountLockVo accountLockVo = new AccountLockVo();
                accountLockVo.setOrderNo(orderNo);
                accountLockVo.setUserId(userId);
                accountLockVo.setAmount(orderInfoVo.getOrderAmount());
                accountLockVo.setContent(orderInfoVo.getOrderDetailVoList().get(0).getItemName());
                //  远程调用 检查与锁定
                Result<AccountLockResultVo> result = userAccountFeignClient.checkAndLock(accountLockVo);
                //  判断检查与锁定是否成功.
                if (result.getCode().intValue()!=200) {
                    throw new GuiguException(ResultCodeEnum.ACCOUNT_LESS);
                    //  throw new GuiguException(result.getCode(),result.getMessage());
                }
                //  保存交易记录
                this.saveOrder(orderInfoVo,userId,orderNo);
                //  发送消息扣减金额
                kafkaService.sendMsg(KafkaConstant.QUEUE_ACCOUNT_MINUS,orderNo);
                //  返回订单编号
                return orderNo;
            } catch (GuiguException e) {
                log.error("检查与锁定出现异常",e.getMessage());
                //  解锁金额：
                kafkaService.sendMsg(KafkaConstant.QUEUE_ACCOUNT_UNLOCK,orderNo);
                e.getMessage();
            }
        }
        //  走微信支付：
        return orderNo;
    }

    @Override
    public OrderInfo getOrderInfo(String orderNo) {
        //  select * from order_info where order_no = ?
        return this.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo,orderNo));
    }

    @Override
    public void orderCancel(long orderId) {
        //  修改订单记录
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(SystemConstant.ORDER_STATUS_CANCEL);
        this.updateById(orderInfo);
    }

    /**
     * 保存订单交易记录
     * @param orderInfoVo
     * @param userId
     * @param orderNo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrder(OrderInfoVo orderInfoVo, Long userId, String orderNo) {
        /*
         order_derate
         order_detail
         order_info
         */
        OrderInfo orderInfo = new OrderInfo();
        //  赋值：
        orderInfo.setUserId(userId);
        orderInfo.setOrderNo(orderNo);
        //  订单title;
        orderInfo.setOrderTitle(orderInfoVo.getOrderDetailVoList().get(0).getItemName());
        orderInfo.setOrderStatus(SystemConstant.ORDER_STATUS_UNPAID);
        BeanUtils.copyProperties(orderInfoVo,orderInfo);
        //  保存订单
        this.save(orderInfo);
        //  先获取到订单明细.
        List<OrderDetailVo> orderDetailVoList = orderInfoVo.getOrderDetailVoList();
        if (!CollectionUtils.isEmpty(orderDetailVoList)){
            //  遍历集合
            //            orderDetailVoList.stream().forEach(orderDetailVo -> {
            //                //  创建订单明细
            //                OrderDetail orderDetail = new OrderDetail();
            //                //  先新增了，@TableId(type = IdType.AUTO) 就能够将自增的id赋值给orderInfo实体类了。
            //                orderDetail.setOrderId(orderInfo.getId());
            //                //  属性拷贝
            //                BeanUtils.copyProperties(orderDetailVo,orderDetail);
            //                //  将这个对象保存数据库. 执行多条sql
            //                orderDetailMapper.insert(orderDetail);
            //            });
            List<OrderDetail> orderDetailList = orderDetailVoList.stream().map(orderDetailVo -> {
                //  创建订单明细
                OrderDetail orderDetail = new OrderDetail();
                //  先新增了，@TableId(type = IdType.AUTO) 就能够将自增的id赋值给orderInfo实体类了。
                orderDetail.setOrderId(orderInfo.getId());
                //  属性拷贝
                BeanUtils.copyProperties(orderDetailVo, orderDetail);
                //  将这个对象保存数据库.
                return orderDetail;
            }).collect(Collectors.toList());
            //  批量插入数据。 执行的一条sql
            orderDetailService.saveBatch(orderDetailList);
        }
        //  只有购买声音的时候，不支持减免.
        List<OrderDerateVo> orderDerateVoList = orderInfoVo.getOrderDerateVoList();
        if (!CollectionUtils.isEmpty(orderDerateVoList)){
            //  循环遍历.
            orderDerateVoList.forEach(orderDerateVo -> {
                //  创建减免对象
                OrderDerate orderDerate = new OrderDerate();
                //  赋值
                orderDerate.setOrderId(orderInfo.getId());
                orderDerate.setDerateType(orderDerateVo.getDerateType());
                orderDerate.setDerateAmount(orderDerateVo.getDerateAmount());
                //  插入数据.
                orderDerateMapper.insert(orderDerate);
            });
        }

        //  判断支付类型：
        if (orderInfoVo.getPayWay().equals(SystemConstant.ORDER_PAY_WAY_WEIXIN)){
            //  微信支付 -- 发送延迟消息做取消订单业务逻辑. kafka不支持延迟消息.所以在此需要自定义一个延迟消息.redissonClient            kafkaService.sendDelayMsg(orderNo);
            //  kafkaService.sendMsg()  this.sendDelayMessage(orderNo);
            this.sendDelayMessage(orderInfo.getId());
        } else {
            //  余额支付 处理更新交易记录. UserPaidRecordVo--发生到消息队列
            this.orderPaySuccess(orderNo);
        }

    }

    /**
     * 保存用户支付记录
     * @param orderNo
     */
    @Override
    public void orderPaySuccess(String orderNo) {
        //  更新订单支付状态.
        OrderInfo orderInfoUpd = new OrderInfo();
        orderInfoUpd.setOrderStatus(SystemConstant.ORDER_STATUS_PAID);
        //  第一个参数是，实体类-表示要修改的字段； 第二个参数是更新的条件
        LambdaUpdateWrapper<OrderInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(OrderInfo::getOrderNo,orderNo);
        //  使用xxxMapper：update order_info set order_status = '0902' where order_no = ? and is_delete = 0;
        //  如果是自己在xml中写的sal 语句，不会添加 is_delete = 0
        orderInfoMapper.update(orderInfoUpd,wrapper);
        //  已知 orderNo 求：orderInfo；
        OrderInfo orderInfo = this.getOrderInfoByOrderNo(orderNo);
        //  为了提高系统的响应速度，用户体验度！在此，使用异步形式记录用户购买记录信息. 要想做一致性；使用seata保证分布式事务。
        UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
        userPaidRecordVo.setUserId(orderInfo.getUserId());
        userPaidRecordVo.setOrderNo(orderNo);
        userPaidRecordVo.setItemType(orderInfo.getItemType());

        //  orderInfo.getOrderDetailList(); 集合中的itemId
        List<Long> itemIdList = orderInfo.getOrderDetailList().stream().map(OrderDetail::getItemId).collect(Collectors.toList());
        userPaidRecordVo.setItemIdList(itemIdList);
        //  发送消息.
        kafkaService.sendMsg(KafkaConstant.QUEUE_USER_PAY_RECORD,JSON.toJSONString(userPaidRecordVo));

    }

    @Override
    public IPage<OrderInfo> findUserPage(Page<OrderInfo> infoPage, Long userId, String orderStatus) {
        //  调用mapper层方法
        IPage<OrderInfo> orderInfoIPage = orderInfoMapper.selectUserPage(infoPage,userId,orderStatus);
        //  获取到所有数据集合：
        orderInfoIPage.getRecords().stream().forEach(orderInfo -> {
            //  赋值支付方式名称
            orderInfo.setPayWayName(this.getPayWayName(orderInfo.getPayWay()));
            //  赋值订单状态名称
            orderInfo.setOrderStatusName(this.getOrderStatusName(orderInfo.getOrderStatus()));
        });
        //  返回对象
        return orderInfoIPage;
    }

    /**
     * 根据订单状态获取到订单名称
     * @param orderStatus
     * @return
     */
    private String getOrderStatusName(String orderStatus) {
        //  声明订单状态名称
        String orderStatusName = "";
        //  判断
        if (SystemConstant.ORDER_STATUS_UNPAID.equals(orderStatus)){
            orderStatusName = "未支付";
        } else if (SystemConstant.ORDER_STATUS_PAID.equals(orderStatus)) {
            orderStatusName = "已支付";
        } else {
            orderStatusName = "已取消";
        }
        //  返回
        return orderStatusName;
    }

    /**
     * 根据orderNo 获取到订单对象
     * @param orderNo
     * @return
     */
    @Override
    public OrderInfo getOrderInfoByOrderNo(String orderNo) {
        //  select * from order_info where  order_no = ?
        OrderInfo orderInfo = this.orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo,orderNo));
        //  获取订单明细
        List<OrderDetail> orderDetailList = this.orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
        //  赋值订单明细.
        orderInfo.setOrderDetailList(orderDetailList);
        //  获取减免明细.
        List<OrderDerate> orderDerateList = this.orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDerateList(orderDerateList);
        //  获取支付方式：
        orderInfo.setPayWayName(this.getPayWayName(orderInfo.getPayWay()));
        //  返回对象
        return orderInfo;
    }

    /**
     * 根据payWay 返回支付名称
     * @param payWay
     * @return
     */
    private String getPayWayName(String payWay) {
        //  声明一个对象
        return SystemConstant.ORDER_PAY_WAY_WEIXIN.equals(payWay)?"微信支付":"余额支付";
    }

    /**
     * 发送延迟消息。kafka 不支持延迟消息.
     * @param orderId
     */
    private void sendDelayMessage(Long orderId) {
        try {
            //  使用redissonClient
            RBlockingQueue<Object> blockingQueue = this.redissonClient.getBlockingQueue(KafkaConstant.QUEUE_ORDER_CANCEL);
            RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
            //  blockingQueue.offer()
            //  发生消息. orderId
            delayedQueue.offer(orderId.toString(),KafkaConstant.DELAY_TIME, TimeUnit.SECONDS);
            log.info("发送成功."+orderId);
            //  put take offer
        } catch (Exception e) {
            log.info("发送失败."+orderId);
            throw new RuntimeException(e);
        }
    }

    @Override
    public OrderInfoVo trade(TradeVo tradeVo, Long userId) {
        //  声明一些变量：来存储价格信息.
        //  原始金额
        BigDecimal originalAmount = new BigDecimal("0.00");
        //  减免总金额
        BigDecimal derateAmount = new BigDecimal("0.00");
        //  订单总金额
        BigDecimal orderAmount = new BigDecimal("0.00");
        //  声明一个订单明细集合
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        //  声明一个订单减免明细集合
        List<OrderDerateVo> orderDerateVoList = new ArrayList<>();

        //  获取用户对象
        Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
        Assert.notNull(userInfoVoResult, "用户信息结果集为空");
        UserInfoVo userInfoVo = userInfoVoResult.getData();

        //  判断购买类型
        if (tradeVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)) {
            //  购买专辑
            //  判断用户是否购买过专辑
            Result<Boolean> isPaidAlbumResult = userInfoFeignClient.isPaidAlbum(tradeVo.getItemId());
            Assert.notNull(isPaidAlbumResult, "返回结果集为空");
            Boolean result = isPaidAlbumResult.getData();
            //  判断
            if (result) {
                throw new GuiguException(ResultCodeEnum.ORDER_SUBMIT_REPEAT);
            }
            //  获取到专辑信息
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(tradeVo.getItemId());
            Assert.notNull(albumInfoResult, "返回结果集为空");
            AlbumInfo albumInfo = albumInfoResult.getData();
            //  首次购买！
            if (userInfoVo.getIsVip().intValue() == 0) {
                //  原始金额 1000
                originalAmount = albumInfo.getPrice();
                //  非vip - 判断当前专辑是否打折
                if (albumInfo.getDiscount().intValue() != -1) {
                    //  说明有折扣 8 800; 1000*(10-9) = 1000/10=100
                    //  derateAmount = originalAmount.multiply(new BigDecimal("10").subtract(new BigDecimal(String.valueOf(albumInfo.getDiscount()))))
                    derateAmount = originalAmount.multiply(new BigDecimal("10").subtract(new BigDecimal(String.valueOf(albumInfo.getDiscount())))).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
                }
                //  总金额；
                orderAmount = originalAmount.subtract(derateAmount);
            } else {
                //  原始金额 1000
                originalAmount = albumInfo.getPrice();
                //  非vip - 判断当前专辑是否打折
                if (albumInfo.getVipDiscount().intValue() != -1) {
                    //  说明有折扣 8 800; 1000*(10-8) = 2000/10=200
                    //  derateAmount = originalAmount.multiply(new BigDecimal("10").subtract(new BigDecimal(String.valueOf(albumInfo.getDiscount()))))
                    derateAmount = originalAmount.multiply(new BigDecimal("10").subtract(new BigDecimal(String.valueOf(albumInfo.getVipDiscount())))).divide(new BigDecimal("10"), 2, RoundingMode.HALF_UP);
                }
                //  总金额；
                orderAmount = originalAmount.subtract(derateAmount);
            }
            //  赋值订单明细.
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setItemId(tradeVo.getItemId());
            orderDetailVo.setItemName("购买专辑" + albumInfo.getAlbumTitle());
            orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
            orderDetailVo.setItemPrice(orderAmount);
            //  将订单明细添加到集合中
            orderDetailVoList.add(orderDetailVo);
            //  判断是否有减免金额：
            if (derateAmount.compareTo(BigDecimal.ZERO) != 0) {
                //  创建减免金额对象
                OrderDerateVo orderDerateVo = new OrderDerateVo();
                orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_ALBUM_DISCOUNT);
                orderDerateVo.setDerateAmount(derateAmount);
                //  添加到集合中
                orderDerateVoList.add(orderDerateVo);
            }

        } else if (tradeVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)) {
            //  购买声音
            if (tradeVo.getTrackCount().intValue() < 0) {
                throw new GuiguException(ResultCodeEnum.ARGUMENT_VALID_ERROR);
            }
            //  获取到声音Id
            Long trackId = tradeVo.getItemId();
            //  购买集数
            Integer trackCount = tradeVo.getTrackCount();
            //  获取到详情列表：
            Result<List<TrackInfo>> trackInfoListResult = trackInfoFeignClient.findPaidTrackInfoList(trackId, trackCount);
            Assert.notNull(trackInfoListResult, "声音列表为空");
            List<TrackInfo> trackInfoList = trackInfoListResult.getData();
            Assert.notNull(trackInfoList, "声音为空");
            //  获取到专辑对象. albumInfo.getPrice()*trackCount;
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(trackInfoList.get(0).getAlbumId());
            Assert.notNull(albumInfoResult, "专辑结果集为空");
            AlbumInfo albumInfo = albumInfoResult.getData();
            //  购买声音不支持折扣：
            //  originalAmount = 0;
            originalAmount = trackCount.intValue() > 0 ? albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(trackCount))) : albumInfo.getPrice();
            //  订单总价
            orderAmount = originalAmount;
            //  赋值订单明细 应该放在循环中处理。
            orderDetailVoList = trackInfoList.stream().map(trackInfo -> {
                //  创建对象
                OrderDetailVo orderDetailVo = new OrderDetailVo();
                orderDetailVo.setItemId(trackInfo.getId());
                orderDetailVo.setItemName(trackInfo.getTrackTitle());
                orderDetailVo.setItemPrice(albumInfo.getPrice());
                orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
                //  返回对象
                return orderDetailVo;
            }).collect(Collectors.toList());
        } else {
            //  购买vip
            //  1.  获取购买vip的配置信息.
            //  通过itemId查询购买的vip时效;
            Result<VipServiceConfig> vipServiceConfigResult = vipServiceConfigFeignClient.getVipServiceConfig(tradeVo.getItemId());
            Assert.notNull(vipServiceConfigResult, "vip 配置信息为空");
            VipServiceConfig vipServiceConfig = vipServiceConfigResult.getData();
            //  2.  赋值订单金额信息.
            originalAmount = vipServiceConfig.getPrice();
            //  减免金额
            derateAmount = originalAmount.subtract(vipServiceConfig.getDiscountPrice());
            //  实际金额
            orderAmount = vipServiceConfig.getDiscountPrice();

            //  赋值订单明细.
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setItemId(tradeVo.getItemId());
            orderDetailVo.setItemName("购买VIP" + vipServiceConfig.getName());
            orderDetailVo.setItemUrl(vipServiceConfig.getImageUrl());
            orderDetailVo.setItemPrice(orderAmount);
            //  将订单明细添加到集合中
            orderDetailVoList.add(orderDetailVo);

            //  判断是否有减免金额：
            if (derateAmount.compareTo(BigDecimal.ZERO) != 0) {
                //  创建减免金额对象
                OrderDerateVo orderDerateVo = new OrderDerateVo();
                orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_VIP_SERVICE_DISCOUNT);
                orderDerateVo.setDerateAmount(derateAmount);
                //  添加到集合中
                orderDerateVoList.add(orderDerateVo);
            }
        }
        //  声明一个流水号
        String tradeNo = UUID.randomUUID().toString().replaceAll("-", "");
        String tradeNoKey = "user:trade:" + userId;
        //  存储到缓存一份,防止重复提交使用！
        this.redisTemplate.opsForValue().set(tradeNoKey, tradeNo);
        //  创建对象
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setTradeNo(tradeNo);
        orderInfoVo.setPayWay("");
        orderInfoVo.setItemType(tradeVo.getItemType());
        orderInfoVo.setOriginalAmount(originalAmount);
        orderInfoVo.setDerateAmount(derateAmount);
        orderInfoVo.setOrderAmount(orderAmount);
        orderInfoVo.setOrderDetailVoList(orderDetailVoList);
        orderInfoVo.setOrderDerateVoList(orderDerateVoList);
        orderInfoVo.setTimestamp(SignHelper.getTimestamp());

        //  orderInfoVo--> JsonString
        String strJson = JSON.toJSONString(orderInfoVo);
        System.out.println("strJson:\t" + strJson);
        Map map = JSON.parseObject(strJson, Map.class);
        System.out.println("map:\t" + JSON.toJSONString(map));
        //  设置签名-校验订单信息是否正确！
        String sign = SignHelper.getSign(map);
        //  JSON.toJSONString(map);
        orderInfoVo.setSign(sign);
        //  返回数据
        return orderInfoVo;
    }
}
